"""
动作组编辑器图形界面
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from typing import Dict, List, Optional
from .action_editor import ActionEditor, ActionStep
from ..control import MotionController
import time


class ActionEditorGUI:
    """动作组编辑器图形界面"""

    def __init__(self):
        """初始化界面"""
        self.root = tk.Tk()
        self.root.title("六足机器人动作组编辑器")
        self.root.geometry("800x600")

        # 初始化编辑器
        self.motion_controller = MotionController()
        self.editor = ActionEditor(self.motion_controller)

        # 创建界面元素
        self._create_widgets()

    def _create_widgets(self):
        """创建界面元素"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 动作组列表
        group_frame = ttk.LabelFrame(main_frame, text="动作组", padding="5")
        group_frame.grid(
            row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=5, pady=5
        )

        self.group_listbox = tk.Listbox(group_frame, width=30, height=10)
        self.group_listbox.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        self.group_listbox.bind("<<ListboxSelect>>", self._on_group_select)

        group_buttons = ttk.Frame(group_frame)
        group_buttons.grid(row=1, column=0, sticky=(tk.W, tk.E))

        ttk.Button(group_buttons, text="新建", command=self._create_group).grid(
            row=0, column=0, padx=5
        )
        ttk.Button(group_buttons, text="复制", command=self._copy_group).grid(
            row=0, column=1, padx=5
        )
        ttk.Button(group_buttons, text="删除", command=self._delete_group).grid(
            row=0, column=2, padx=5
        )

        # 动作步骤列表
        step_frame = ttk.LabelFrame(main_frame, text="动作步骤", padding="5")
        step_frame.grid(
            row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), padx=5, pady=5
        )

        self.step_listbox = tk.Listbox(step_frame, width=50, height=10)
        self.step_listbox.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        step_buttons = ttk.Frame(step_frame)
        step_buttons.grid(row=1, column=0, sticky=(tk.W, tk.E))

        ttk.Button(step_buttons, text="添加舵机", command=self._add_servo_step).grid(
            row=0, column=0, padx=5
        )
        ttk.Button(step_buttons, text="添加延迟", command=self._add_delay_step).grid(
            row=0, column=1, padx=5
        )
        ttk.Button(
            step_buttons, text="添加复合动作", command=self._add_composite_step
        ).grid(row=0, column=2, padx=5)
        ttk.Button(step_buttons, text="添加循环动作", command=self._add_loop_step).grid(
            row=0, column=3, padx=5
        )
        ttk.Button(step_buttons, text="删除", command=self._delete_step).grid(
            row=0, column=4, padx=5
        )

        # 预览和控制按钮
        control_frame = ttk.Frame(main_frame)
        control_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

        ttk.Button(control_frame, text="预览", command=self._preview).grid(
            row=0, column=0, padx=5
        )
        ttk.Button(control_frame, text="停止", command=self._stop).grid(
            row=0, column=1, padx=5
        )
        ttk.Button(control_frame, text="验证", command=self._validate).grid(
            row=0, column=2, padx=5
        )
        ttk.Button(control_frame, text="导出", command=self._export).grid(
            row=0, column=3, padx=5
        )
        ttk.Button(control_frame, text="导入", command=self._import).grid(
            row=0, column=4, padx=5
        )
        ttk.Button(
            control_frame, text="版本历史", command=self._show_version_history
        ).grid(row=0, column=5, padx=5)

        # 状态栏
        self.status_var = tk.StringVar()
        status_bar = ttk.Label(
            main_frame, textvariable=self.status_var, relief=tk.SUNKEN
        )
        status_bar.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

    def _on_group_select(self, event):
        """动作组选择事件处理"""
        selection = self.group_listbox.curselection()
        if selection:
            name = self.group_listbox.get(selection[0])
            self.editor.load_group(name)
            self._update_step_list()

    def _update_group_list(self):
        """更新动作组列表"""
        self.group_listbox.delete(0, tk.END)
        for name in self.editor.groups:
            self.group_listbox.insert(tk.END, name)

    def _update_step_list(self):
        """更新动作步骤列表"""
        self.step_listbox.delete(0, tk.END)
        if self.editor.current_group:
            for i, step in enumerate(self.editor.current_group.steps):
                if step.type == "servo":
                    self.step_listbox.insert(
                        tk.END,
                        f"步骤 {i+1}: 舵机 {step.servo_id} -> 位置 {step.position}, 速度 {step.speed}",
                    )
                elif step.type == "delay":
                    self.step_listbox.insert(
                        tk.END, f"步骤 {i+1}: 延迟 {step.duration}秒"
                    )
                elif step.type == "composite":
                    self.step_listbox.insert(
                        tk.END, f"步骤 {i+1}: 复合动作 ({len(step.sub_steps)}个子步骤)"
                    )
                elif step.type == "loop":
                    self.step_listbox.insert(
                        tk.END,
                        f"步骤 {i+1}: 循环动作 (循环{step.loop_count}次, {len(step.loop_steps)}个步骤)",
                    )

    def _create_group(self):
        """创建新动作组"""
        dialog = tk.Toplevel(self.root)
        dialog.title("新建动作组")
        dialog.geometry("300x150")

        ttk.Label(dialog, text="名称:").grid(row=0, column=0, padx=5, pady=5)
        name_entry = ttk.Entry(dialog)
        name_entry.grid(row=0, column=1, padx=5, pady=5)

        ttk.Label(dialog, text="描述:").grid(row=1, column=0, padx=5, pady=5)
        desc_entry = ttk.Entry(dialog)
        desc_entry.grid(row=1, column=1, padx=5, pady=5)

        def on_ok():
            name = name_entry.get()
            desc = desc_entry.get()
            if name:
                try:
                    group = self.editor.create_group(name)
                    group.description = desc
                    self._update_group_list()
                    dialog.destroy()
                except ValueError as e:
                    messagebox.showerror("错误", str(e))

        ttk.Button(dialog, text="确定", command=on_ok).grid(
            row=2, column=0, columnspan=2, pady=10
        )

    def _copy_group(self):
        """复制动作组"""
        selection = self.group_listbox.curselection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        name = self.group_listbox.get(selection[0])
        dialog = tk.Toplevel(self.root)
        dialog.title("复制动作组")
        dialog.geometry("300x100")

        ttk.Label(dialog, text="新名称:").grid(row=0, column=0, padx=5, pady=5)
        name_entry = ttk.Entry(dialog)
        name_entry.grid(row=0, column=1, padx=5, pady=5)

        def on_ok():
            new_name = name_entry.get()
            if new_name:
                try:
                    self.editor.copy_group(name, new_name)
                    self._update_group_list()
                    dialog.destroy()
                except ValueError as e:
                    messagebox.showerror("错误", str(e))

        ttk.Button(dialog, text="确定", command=on_ok).grid(
            row=1, column=0, columnspan=2, pady=10
        )

    def _delete_group(self):
        """删除动作组"""
        selection = self.group_listbox.curselection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        name = self.group_listbox.get(selection[0])
        if messagebox.askyesno("确认", f"确定要删除动作组 '{name}' 吗？"):
            try:
                self.editor.delete_group(name)
                self._update_group_list()
            except ValueError as e:
                messagebox.showerror("错误", str(e))

    def _add_servo_step(self):
        """添加舵机动作步骤"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        dialog = tk.Toplevel(self.root)
        dialog.title("添加舵机动作")
        dialog.geometry("300x200")

        ttk.Label(dialog, text="舵机ID:").grid(row=0, column=0, padx=5, pady=5)
        id_entry = ttk.Entry(dialog)
        id_entry.grid(row=0, column=1, padx=5, pady=5)

        ttk.Label(dialog, text="位置:").grid(row=1, column=0, padx=5, pady=5)
        pos_entry = ttk.Entry(dialog)
        pos_entry.grid(row=1, column=1, padx=5, pady=5)

        ttk.Label(dialog, text="速度:").grid(row=2, column=0, padx=5, pady=5)
        speed_entry = ttk.Entry(dialog)
        speed_entry.grid(row=2, column=1, padx=5, pady=5)

        def on_ok():
            try:
                servo_id = int(id_entry.get())
                position = int(pos_entry.get())
                speed = int(speed_entry.get())
                self.editor.add_servo_step(servo_id, position, speed)
                self._update_step_list()
                dialog.destroy()
            except ValueError:
                messagebox.showerror("错误", "请输入有效的数字")

        ttk.Button(dialog, text="确定", command=on_ok).grid(
            row=3, column=0, columnspan=2, pady=10
        )

    def _add_delay_step(self):
        """添加延迟步骤"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        dialog = tk.Toplevel(self.root)
        dialog.title("添加延迟")
        dialog.geometry("300x100")

        ttk.Label(dialog, text="延迟时间(秒):").grid(row=0, column=0, padx=5, pady=5)
        duration_entry = ttk.Entry(dialog)
        duration_entry.grid(row=0, column=1, padx=5, pady=5)

        def on_ok():
            try:
                duration = float(duration_entry.get())
                if duration <= 0:
                    raise ValueError
                self.editor.add_delay_step(duration)
                self._update_step_list()
                dialog.destroy()
            except ValueError:
                messagebox.showerror("错误", "请输入有效的延迟时间")

        ttk.Button(dialog, text="确定", command=on_ok).grid(
            row=1, column=0, columnspan=2, pady=10
        )

    def _add_composite_step(self):
        """添加复合动作步骤"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        dialog = tk.Toplevel(self.root)
        dialog.title("添加复合动作")
        dialog.geometry("400x300")

        # 创建子步骤列表
        sub_steps_frame = ttk.LabelFrame(dialog, text="子步骤", padding="5")
        sub_steps_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        sub_steps_listbox = tk.Listbox(sub_steps_frame, width=50, height=10)
        sub_steps_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(
            sub_steps_frame, orient=tk.VERTICAL, command=sub_steps_listbox.yview
        )
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        sub_steps_listbox.config(yscrollcommand=scrollbar.set)

        sub_steps = []

        def add_servo_sub_step():
            sub_dialog = tk.Toplevel(dialog)
            sub_dialog.title("添加舵机子步骤")
            sub_dialog.geometry("300x150")

            ttk.Label(sub_dialog, text="舵机ID:").grid(row=0, column=0, padx=5, pady=5)
            id_entry = ttk.Entry(sub_dialog)
            id_entry.grid(row=0, column=1, padx=5, pady=5)

            ttk.Label(sub_dialog, text="位置:").grid(row=1, column=0, padx=5, pady=5)
            pos_entry = ttk.Entry(sub_dialog)
            pos_entry.grid(row=1, column=1, padx=5, pady=5)

            ttk.Label(sub_dialog, text="速度:").grid(row=2, column=0, padx=5, pady=5)
            speed_entry = ttk.Entry(sub_dialog)
            speed_entry.grid(row=2, column=1, padx=5, pady=5)

            def on_ok():
                try:
                    servo_id = int(id_entry.get())
                    position = int(pos_entry.get())
                    speed = int(speed_entry.get())
                    step = ActionStep(
                        type="servo", servo_id=servo_id, position=position, speed=speed
                    )
                    sub_steps.append(step)
                    sub_steps_listbox.insert(
                        tk.END, f"舵机 {servo_id} -> 位置 {position}, 速度 {speed}"
                    )
                    sub_dialog.destroy()
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的数字")

            ttk.Button(sub_dialog, text="确定", command=on_ok).grid(
                row=3, column=0, columnspan=2, pady=10
            )

        def add_delay_sub_step():
            sub_dialog = tk.Toplevel(dialog)
            sub_dialog.title("添加延迟子步骤")
            sub_dialog.geometry("300x100")

            ttk.Label(sub_dialog, text="延迟时间(秒):").grid(
                row=0, column=0, padx=5, pady=5
            )
            duration_entry = ttk.Entry(sub_dialog)
            duration_entry.grid(row=0, column=1, padx=5, pady=5)

            def on_ok():
                try:
                    duration = float(duration_entry.get())
                    if duration <= 0:
                        raise ValueError
                    step = ActionStep(type="delay", duration=duration)
                    sub_steps.append(step)
                    sub_steps_listbox.insert(tk.END, f"延迟 {duration}秒")
                    sub_dialog.destroy()
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的延迟时间")

            ttk.Button(sub_dialog, text="确定", command=on_ok).grid(
                row=1, column=0, columnspan=2, pady=10
            )

        def on_ok():
            if not sub_steps:
                messagebox.showwarning("警告", "请至少添加一个子步骤")
                return

            self.editor.add_composite_step(sub_steps)
            self._update_step_list()
            dialog.destroy()

        button_frame = ttk.Frame(dialog)
        button_frame.pack(fill=tk.X, padx=5, pady=5)

        ttk.Button(button_frame, text="添加舵机", command=add_servo_sub_step).pack(
            side=tk.LEFT, padx=5
        )
        ttk.Button(button_frame, text="添加延迟", command=add_delay_sub_step).pack(
            side=tk.LEFT, padx=5
        )
        ttk.Button(button_frame, text="确定", command=on_ok).pack(side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消", command=dialog.destroy).pack(
            side=tk.RIGHT, padx=5
        )

    def _add_loop_step(self):
        """添加循环动作步骤"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        dialog = tk.Toplevel(self.root)
        dialog.title("添加循环动作")
        dialog.geometry("400x300")

        # 循环次数
        ttk.Label(dialog, text="循环次数:").grid(row=0, column=0, padx=5, pady=5)
        count_entry = ttk.Entry(dialog)
        count_entry.grid(row=0, column=1, padx=5, pady=5)

        # 创建循环步骤列表
        loop_steps_frame = ttk.LabelFrame(dialog, text="循环步骤", padding="5")
        loop_steps_frame.grid(
            row=1,
            column=0,
            columnspan=2,
            sticky=(tk.W, tk.E, tk.N, tk.S),
            padx=5,
            pady=5,
        )

        loop_steps_listbox = tk.Listbox(loop_steps_frame, width=50, height=10)
        loop_steps_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(
            loop_steps_frame, orient=tk.VERTICAL, command=loop_steps_listbox.yview
        )
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        loop_steps_listbox.config(yscrollcommand=scrollbar.set)

        loop_steps = []

        def add_servo_loop_step():
            sub_dialog = tk.Toplevel(dialog)
            sub_dialog.title("添加舵机循环步骤")
            sub_dialog.geometry("300x150")

            ttk.Label(sub_dialog, text="舵机ID:").grid(row=0, column=0, padx=5, pady=5)
            id_entry = ttk.Entry(sub_dialog)
            id_entry.grid(row=0, column=1, padx=5, pady=5)

            ttk.Label(sub_dialog, text="位置:").grid(row=1, column=0, padx=5, pady=5)
            pos_entry = ttk.Entry(sub_dialog)
            pos_entry.grid(row=1, column=1, padx=5, pady=5)

            ttk.Label(sub_dialog, text="速度:").grid(row=2, column=0, padx=5, pady=5)
            speed_entry = ttk.Entry(sub_dialog)
            speed_entry.grid(row=2, column=1, padx=5, pady=5)

            def on_ok():
                try:
                    servo_id = int(id_entry.get())
                    position = int(pos_entry.get())
                    speed = int(speed_entry.get())
                    step = ActionStep(
                        type="servo", servo_id=servo_id, position=position, speed=speed
                    )
                    loop_steps.append(step)
                    loop_steps_listbox.insert(
                        tk.END, f"舵机 {servo_id} -> 位置 {position}, 速度 {speed}"
                    )
                    sub_dialog.destroy()
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的数字")

            ttk.Button(sub_dialog, text="确定", command=on_ok).grid(
                row=3, column=0, columnspan=2, pady=10
            )

        def add_delay_loop_step():
            sub_dialog = tk.Toplevel(dialog)
            sub_dialog.title("添加延迟循环步骤")
            sub_dialog.geometry("300x100")

            ttk.Label(sub_dialog, text="延迟时间(秒):").grid(
                row=0, column=0, padx=5, pady=5
            )
            duration_entry = ttk.Entry(sub_dialog)
            duration_entry.grid(row=0, column=1, padx=5, pady=5)

            def on_ok():
                try:
                    duration = float(duration_entry.get())
                    if duration <= 0:
                        raise ValueError
                    step = ActionStep(type="delay", duration=duration)
                    loop_steps.append(step)
                    loop_steps_listbox.insert(tk.END, f"延迟 {duration}秒")
                    sub_dialog.destroy()
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的延迟时间")

            ttk.Button(sub_dialog, text="确定", command=on_ok).grid(
                row=1, column=0, columnspan=2, pady=10
            )

        def on_ok():
            try:
                loop_count = int(count_entry.get())
                if loop_count <= 0:
                    raise ValueError
            except ValueError:
                messagebox.showerror("错误", "请输入有效的循环次数")
                return

            if not loop_steps:
                messagebox.showwarning("警告", "请至少添加一个循环步骤")
                return

            self.editor.add_loop_step(loop_count, loop_steps)
            self._update_step_list()
            dialog.destroy()

        button_frame = ttk.Frame(dialog)
        button_frame.grid(
            row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), padx=5, pady=5
        )

        ttk.Button(button_frame, text="添加舵机", command=add_servo_loop_step).pack(
            side=tk.LEFT, padx=5
        )
        ttk.Button(button_frame, text="添加延迟", command=add_delay_loop_step).pack(
            side=tk.LEFT, padx=5
        )
        ttk.Button(button_frame, text="确定", command=on_ok).pack(side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消", command=dialog.destroy).pack(
            side=tk.RIGHT, padx=5
        )

    def _delete_step(self):
        """删除动作步骤"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        selection = self.step_listbox.curselection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个步骤")
            return

        index = selection[0]
        self.editor.current_group.remove_step(index)
        self._update_step_list()

    def _preview(self):
        """预览动作组"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        try:
            self.editor.preview()
            self.status_var.set("预览完成")
        except Exception as e:
            messagebox.showerror("错误", str(e))

    def _stop(self):
        """停止预览"""
        self.motion_controller.stop_all()
        self.status_var.set("已停止")

    def _validate(self):
        """验证动作组"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        is_valid, errors = self.editor.validate_group(self.editor.current_group.name)
        if is_valid:
            messagebox.showinfo("验证", "动作组验证通过")
        else:
            messagebox.showerror("验证失败", "\n".join(errors))

    def _export(self):
        """导出动作组"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        filename = filedialog.asksaveasfilename(
            defaultextension=".json", filetypes=[("JSON文件", "*.json")]
        )
        if filename:
            try:
                self.editor.export_json(filename)
                self.status_var.set(f"已导出到 {filename}")
            except Exception as e:
                messagebox.showerror("错误", str(e))

    def _import(self):
        """导入动作组"""
        filename = filedialog.askopenfilename(filetypes=[("JSON文件", "*.json")])
        if filename:
            try:
                self.editor.import_json(filename)
                self._update_group_list()
                self._update_step_list()
                self.status_var.set(f"已导入 {filename}")
            except Exception as e:
                messagebox.showerror("错误", str(e))

    def _show_version_history(self):
        """显示版本历史"""
        if not self.editor.current_group:
            messagebox.showwarning("警告", "请先选择一个动作组")
            return

        dialog = tk.Toplevel(self.root)
        dialog.title("版本历史")
        dialog.geometry("600x400")

        # 创建版本历史列表
        history_frame = ttk.Frame(dialog)
        history_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        history_listbox = tk.Listbox(history_frame, width=80, height=15)
        history_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(
            history_frame, orient=tk.VERTICAL, command=history_listbox.yview
        )
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        history_listbox.config(yscrollcommand=scrollbar.set)

        # 填充版本历史
        for history in self.editor.current_group.get_version_history():
            timestamp = time.strftime(
                "%Y-%m-%d %H:%M:%S", time.localtime(history["timestamp"])
            )
            history_listbox.insert(tk.END, f"版本 {history['version']} - {timestamp}")

        # 添加恢复按钮
        def on_revert():
            selection = history_listbox.curselection()
            if not selection:
                messagebox.showwarning("警告", "请先选择一个版本")
                return

            version = int(history_listbox.get(selection[0]).split()[1])
            if self.editor.current_group.revert_to_version(version):
                self._update_step_list()
                dialog.destroy()
                messagebox.showinfo("成功", f"已恢复到版本 {version}")
            else:
                messagebox.showerror("错误", "恢复版本失败")

        button_frame = ttk.Frame(dialog)
        button_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(button_frame, text="恢复到选中版本", command=on_revert).pack(
            side=tk.LEFT, padx=5
        )
        ttk.Button(button_frame, text="关闭", command=dialog.destroy).pack(
            side=tk.RIGHT, padx=5
        )

    def run(self):
        """运行界面"""
        self.root.mainloop()
